package cn.laixueit.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.laixueit.base.CommonEnum;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author duxiang
 * @date 2023/12/25 16:26
 */

@Component
public class CommonUtils {

    /**
     * 根据原始名称进行生产随机的新名称，会自动去除特殊符号
     * @return
     */
    public String randomName(String name){
        //加密工具
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        //加密配置
        EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
        //加密算法，写死即可
//        config.setAlgorithm("PBEWithMD5AndDES");
        config.setAlgorithm(CommonEnum.PWD.getEncryption());
        //加密使用salt设置
        config.setPassword(CommonEnum.PWDYAN.getEncryptionYan());
        //应用配置
        encryptor.setConfig(config);
        //需要加密数据
        //加密
        String encrypttext=encryptor.encrypt(name);
        String regEx="[`!@#$%^&*()+=|{}':;',//[//].<>/?！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]";

        Pattern pattern   =   Pattern.compile(regEx);
        Matcher matcher   =   pattern.matcher(encrypttext);

        String newName = matcher.replaceAll("").trim();
        int index = name.lastIndexOf(".");
        if(index !=-1){
            newName += name.substring(index);
        }
        return newName;
    }

    /**
     * 按照当前日期生成文件夹，按照年月日
     * @param dirName
     * @param path 生成目录
     */
    public Map<String,Object> createMkdir(String dirName, String path){
        HashMap<String, Object> map = new HashMap<>();
        try {
            int year = LocalDate.now(ZoneId.systemDefault()).getYear();
            int month = LocalDate.now(ZoneId.systemDefault()).getMonthValue();
            int day = LocalDate.now(ZoneId.systemDefault()).getDayOfMonth();
            String join = StrUtil.join("/", year, month, day);
            if(StringUtils.isNotBlank(dirName)){
                join = StrUtil.join("/",dirName,join);
            }
            File file = FileUtil.mkdir(new File(path, join));
            map.put("file",file);
            map.put("dir",join);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 根据传递的字符串格式进行日期格式化，如果不传递默认返回年的字符串“2024”
     *
     * @param dateFormat 日期格式（可选）
     * @return 返回日期格式的字符串数组
     * @throws RuntimeException 可能会抛出日期格式不正确的的处理异常，建议自行处理
     */
    public List<Map<String, String>> createDate(final String... dateFormat) {
        LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
        List<Map<String, String>> list = Arrays.asList(dateFormat).stream().distinct().filter(StringUtils::isNoneBlank).map(x -> {
            HashMap<String, String> map = new HashMap<>();
            map.put(x, DateUtil.format(now, x));
            return map;
        }).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(list)) {
            return list;
        } else {
            HashMap<String, String> map = new HashMap<>();
            map.put("y", Year.from(now).toString());
            map.put("ym", YearMonth.from(now).toString());
            map.put("ymd", DateUtil.format(now,"yyyyMMdd"));
            list.add(map);
            return list;
        }
    }

    /**
     * 调整时间的时区
     *
     * @param date     需要调整的时间
     * @param timeZone 时区
     * @return 返回调整后的时间
     * @throws ParseException 日期进行格式化时可能出现异常，自行处理
     */
    public Date adjustTimeZone(Date date, TimeZone timeZone) throws ParseException {
        if (ObjectUtil.isEmpty(timeZone)) {
            timeZone = TimeZone.getTimeZone(ZoneId.systemDefault());
        }
        SimpleDateFormat format = new SimpleDateFormat();
        format.setTimeZone(timeZone);
        String s = format.format(date);
        return format.parse(s);
    }

    /**
     * 将对象转换成map，同时移除不需要的字段
     *
     * @param o        需要转换的对象
     * @param isRetain 是否是保留字段 true 为保留，false为删除，null为不操作，直接返回转换后的map
     * @param cloKeys  需要操作的字段key （可选）
     * @return 操作转换后的map
     */
    public LinkedHashMap<String, Object> convertMap(Object o, Boolean isRetain, String... cloKeys) {
        Class aClass = o.getClass();
        Field[] fields = ReflectUtil.getFields(aClass);
        String objJson = JSON.toJSONString(o);
        Map map = JSON.parseObject(objJson, Map.class);
        LinkedHashMap<String, Object> linkedHashMap = new LinkedHashMap<String, Object>(map);
        if(ObjectUtil.isNull(isRetain)){
            return linkedHashMap;
        }
        List<String> keys = Arrays.asList(cloKeys).stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
        if (isRetain) {
            LinkedHashMap<String, Object> hashMap = new LinkedHashMap<>();
            keys.stream().forEach(x->{
                if(ObjectUtil.isNotEmpty(linkedHashMap.get(x))) {
                    hashMap.put(x,linkedHashMap.get(x));
                }
            });
            return hashMap;
        } else {
            if (CollectionUtil.isNotEmpty(keys)) {
                keys.stream().forEach(x -> linkedHashMap.remove(x));
            }
        }
        return linkedHashMap;
    }

    /**
     *  @param t 类型
     * @param sz 片区
     * @param dateStr 时间字符串
     * @param character 分隔字符
     * @return
     */
    public String createCode(String t, String sz, String dateStr,String character){
        String concat = t.concat(sz).concat(dateStr);
        int hashCode = this.hashCode();
        concat = concat.concat(String.valueOf(hashCode));
        if(StringUtils.isNotBlank(character)){
            concat = StrUtil.join(character,t,sz,dateStr);
        }
        return concat;
    }
}
